/*
	MIDAS Context Based Routing
	cbr_debug.cc
	Copyright (c) 2007 Radoslaw Olgierd Schoeneich
	Copyright (c) 2007 Bartlomiej Zolnierkiewicz
	MEAG IT PW
*/

#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <cstdlib>
#include <sstream>
#include <semaphore.h>
#include <time.h>

#include "cbr_debug.h"

sem_t cbr_log_sem;

cbr_Logger * cbr_Logger::logger = NULL;

// by default off, use -d parameter to turn it on
bool debug_cbr = false;

/**
 * CBR logger constructor.
 *
 * @param filename filename string
 */

cbr_Logger::cbr_Logger(const char *filename)
{
	std::ostringstream fileName;

	fileName << filename << "_" << getpid();

	logFile.open(fileName.str().c_str(), std::fstream::out);

	cbr_Logger::logger = this;

	sem_init(&cbr_log_sem, 0, 1);
}

/**
 * CBR logger destructor.
 */

cbr_Logger::~cbr_Logger()
{
	sem_destroy(&cbr_log_sem);
}

/**
 * Logs data to the log file.
 *
 * @param str string to log
 */

void cbr_Logger::logData(const char *str)
{
	time_t t;

	sem_wait(&cbr_log_sem);
	if (time(&t) == - 1)
		logFile << "time() failed\n";
	else {
		char *s = new char[26], *p;

		ctime_r(&t, s);
		p = strstr(s, "\n");
		*p = ' ';

		logFile << s;

		delete[] s;
	}
	logFile << str << std::flush;
	sem_post(&cbr_log_sem);
}

/**
 * Logs data to the log file.
 *
 * @param fmt format string
 *
 * Logs data to the log file given format string and additional
 * parameters.  This is basically a wrapper for logData which
 * accepts multiple parameters.
 */

void cbr_Logger::log(const char *fmt, ...)
{
	char buffer[1024];
	va_list args;

	va_start(args, fmt);
	vsnprintf(buffer, sizeof(buffer), fmt, args);
	va_end(args);

	cbr_Logger::logger->logData(buffer);
}

/**
 * Dumps CBR packet (including header).
 *
 * @param data pointer to the data buffer
 * @param size size of the data buffer
 */

void dump_cbr_data(void *data, int size)
{
	char *p = (char *)data;
	char *buf = new char[1024], *s;
	int i = 0, j = 0;

	while (i < (size/16)*16) {
		s = buf;
		s += sprintf(s, "\t0x%04x:  ", i);
		for (j = 0; j < 16; j += 2)
			s += sprintf(s, "%02x%02x ", *(p+i+j) & 0xff, *(p+i+j+1) & 0xff);
		s += sprintf(s, "  ");
		for (j = 0; j < 16; j++)
			s += sprintf(s, "%c", isgraph(p[i+j]) ? p[i+j] : '.');
		s += sprintf(s, "\n");
		*s = '\0';
		cbr_log("%s", buf);
		i += 16;
	}

	if (i < size) {
		s = buf;
		s += sprintf(s, "\t0x%04x:  ", i);
		j = i;
		while (j < (size / 2) * 2) {
			s += sprintf(s, "%02x%02x ", p[j], p[j+1]);
			j += 2;
		}
		if (size % 2)
			s += sprintf(s, "%02x   ", p[j]);
		j = 16 - size % 16;
		while (j >= 2) {
			s += sprintf(s, "     ");
			j -= 2;
		}
		s += sprintf(s, "  ");
		j = i;
		while (j < size) {
			s += sprintf(s, "%c", isgraph(p[j]) ? p[j] : '.');
			j++;
		}
		s += sprintf(s, "\n");
		*s = '\0';
		cbr_log("%s", buf);
	}

	delete[] buf;
}
